﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GmRectPickGroupEventHandler.h"
#include <stack>
#include "IDocument.h"
#include "IPickResult.h"
#include "IGraphicsNodeReference.h"
#include "IPick.h"
#include "IGroup.h"
#include "ILinkElementProxy.h"
#include "ILinkDocumentElement.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

void GmRectPickGroupEventHandler::Process(gcmp::IDocument* pDoc, gcmp::IPickEventArgs* pArgs, const gcmp::Vector3d& ptStart, const gcmp::Vector3d& ptEnd) const
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc参数为空",L"GDMPLab",L"2024-03-30");
    //在项目文档，轮廓编辑模式环境下，需要保证轮廓线，坡度线优先被拾取;
    if (pDoc->IsFamilyDocument())
        return;

    OwnerPtr<IPickResult> opPickResult = IPickResult::Create();
    OwnerPtr<IPick> opPick = IPick::Create();
    OwnerPtr<IPickResult> resultInput = pArgs->GetPickCandidates().Clone();
    std::vector<OwnerPtr<IPick>>& candidates = resultInput->GetAllPicks();
    if (candidates.size() != 1)
    {
        return;
    }

    const std::vector<OwnerPtr<IGraphicsNodeReference>>& vGNodeReference = candidates[0]->GetAllGraphicsNodeReferences();
    UnorderedElementIdSet groupIds;
    for (auto it = vGNodeReference.cbegin(); it != vGNodeReference.cend(); ++it)
    {
        IElement* pEle = pDoc->GetElement((*it)->GetElementId());
        if (!pEle)
            continue;

        if (IGroup* pGroup = quick_cast<IGroup>(pEle))
        {
            if (pGroup->IsSubElementSnapble() == true)
                continue;
        }

        IGroup* pGroup = nullptr;
        if (ILinkElementProxy* pLinkEleProxy = quick_cast<ILinkElementProxy>(pEle))
        {
            const ILinkDocumentElement* pLinkDocElement = pLinkEleProxy->GetLinkDocumentElement();
            if (pLinkDocElement)
            {
                pGroup = quick_cast<IGroup>(pDoc->GetElement(pLinkDocElement->GetGroupId()));
            }
        }
        else
        {
            pGroup = quick_cast<IGroup>(pDoc->GetElement(pEle->GetGroupId()));
        }

        std::stack<IGroup*> stackParentGroups;
        while (pGroup != nullptr)
        {
            stackParentGroups.push(pGroup);
            pGroup = quick_cast<IGroup>(pDoc->GetElement(pGroup->GetGroupId()));
        }

        bool bAdd = false;
        while (!stackParentGroups.empty())
        {
            // 自顶向下处理;
            pGroup = stackParentGroups.top();
            stackParentGroups.pop();

            if (pGroup && pGroup->IsSubElementSnapble() == false)
            {
                ElementId groupId = pGroup->GetElementId();
                if (std::find(groupIds.begin(), groupIds.end(), groupId) == groupIds.end())
                {
                    OwnerPtr<IGraphicsNodeReference> nodeRef = IGraphicsNodeReference::CreateGraphicsElementShapeReference(groupId);
                    if (!nodeRef || nodeRef.get() == nullptr)
                    {
                        continue;
                    }
                    OwnerPtr<GraphicsNodeAndTransform> originalNodeInfo = (*it)->GetIntersectGraphicsNode();
                    if (originalNodeInfo && originalNodeInfo.get())
                    {
                        nodeRef->SetIntersectData((*it)->GetUntransformedIntersectPoint(), (originalNodeInfo->m_wpGraphicsNode).Get(), (originalNodeInfo->m_opTransfrom).get());
                    }
                    opPick->AddGraphicsNodeReference(*(nodeRef.get()));

                    groupIds.emplace(groupId);
                }
                bAdd = true;
                break;
            }
        }
        if (bAdd)
        {
            continue;
        }
        ///////////////////////////////////////////////////////////////////

        opPick->AddGraphicsNodeReference(*(it->get()));
    }
    opPickResult->AddPick(TransferOwnership(opPick));
    pArgs->SetPickCandidates(*opPickResult);
}